﻿using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.Geometry;
using Rhino.Input;
using Rhino.Input.Custom;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace YangTools.RhinoHelper
{
    class Block
    {
        /// <summary>
        /// 获取当前文档空间中的所有的图块定义的名字
        /// </summary>
        private static List<string> blockNames
        {
            get
            {
                var instanceDefinitions = RhinoDoc.ActiveDoc.InstanceDefinitions;
                return instanceDefinitions.Select(i => i.Name).ToList();
            }
        }

        // DuplicateBlock 复制图块定义
        /// <summary>
        /// 复制一个图块的定义，创建新的图块，两个定义只有名字不同；使用自动名称可以保证不会和已有图块重名，新图块名字规则：原图块名字 + # + 序号
        /// </summary>
        /// <param name="block">要被复制的图块引例</param>
        /// <returns>返回图块定义的索引</returns>
        public static int CopyBlock(InstanceObject block)
        {
            // 设置新的图块的名字，保证新名字不是已经存在的图块
            // 新图块名字规则：原图块名字 + # + 序号
            var blockName = block.InstanceDefinition.Name; // 图块的名字
            int i = 1;
            string newName;
            while (true)
            {
                newName = blockName + "#" + i.ToString();
                if (blockNames.Contains(newName))
                {
                    i++;
                }
                else
                {
                    break;
                }
            }

            return DuplicateBlock(block, newName);
        }
        /// <summary>
        /// 复制一个图块的定义，创建新的图块，两个定义只有名字不同
        /// </summary>
        /// <param name="block">要被复制的图块引例</param>
        /// <param name="newName">新的名字</param>
        /// <returns>返回图块定义的索引</returns>
        public static int DuplicateBlock(InstanceObject block, string newName)
        {
            // 这些物体的位置：把图块的基准点对准原点后的物体的位置
            var objects = block.InstanceDefinition.GetObjects().Select(o => o.Geometry).ToList(); // 图块中的物体 List<GeometryBase>

            var basePoint = block.InsertionPoint; // 块的插入基准点
            var blockAttribute = block.Attributes; // 图块的属性


            // 以（0，0，0）为基准点，此时创建的图块的基准点的相对位置没有改变
            int index = RhinoDoc.ActiveDoc.InstanceDefinitions.Add(newName, block.InstanceDefinition.Description, new Point3d(0, 0, 0), objects);

            return index;
        }

        // ChangeSubObjectsAttribute 改变图块子物体的属性
        /// <summary>
        /// 改变图块的子物体的属性
        /// </summary>
        /// <param name="instanceDefinitionIndex">图块定义的索引</param>
        /// <param name="changer">子物体属性改变的方法委托</param>
        public static void ChangeSubObjectsAttribute(List<int> instanceDefinitionIndex, Func<ObjectAttributes, ObjectAttributes> changer)
        {
            foreach (int index in instanceDefinitionIndex)
            {
                var definitionTable = RhinoDoc.ActiveDoc.InstanceDefinitions;
                var subObjects = definitionTable[index].GetObjects();

                var subGeometryBase = subObjects.Select(o => o.Geometry);
                var subAttributes = subObjects.Select(so => changer(so.Attributes));

                definitionTable.ModifyGeometry(index, subGeometryBase, subAttributes);
            }
        }
    }
}
